`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2017/10/23 15:21:30
// Design Name: 
// Module Name: controller
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module controller(
	input wire clk,rst,
	//decode stage
	input wire[5:0] opD,functD,rtD,
	output wire pcsrcD,branchD,equalD,jumpD,jalD,jrD,balD,
	output wire mfhiD, mfloD,//yyx
	output wire hi_writeD,lo_writeD,//yyx
	//execute stage
	//input wire flushE,
	output wire memtoregE,alusrcE,
	output wire regdstE,regwriteE,	
	output wire[4:0] alucontrolE,
	output wire jalE,balE,
	output wire mfhiE,mfloE,//yyx
	output wire hi_writeE,lo_writeE,//yyx
	output wire [1:0] hi_mdrE,lo_mdrE,

	//mem stage
	output wire memtoregM,memwriteM,
				regwriteM,
	output wire [1:0] memsizeM,
	output wire memsigndM,
	output wire hi_writeM, lo_writeM,//yyx
	//write back stage
	output wire memtoregW,regwriteW,
	output wire [1:0] memsizeW,
	output wire memsigndW,
	output wire hi_writeW, lo_writeW,//yyx

	input wire stallE,
    input wire flushE

    );
	
	//decode stage
	wire[1:0] aluopD;
	wire memtoregD,memwriteD,alusrcD,
		regdstD,regwriteD;
	wire[4:0] alucontrolD;
	wire [1:0] memsizeD;
	wire memsigndD;
	wire [1:0] hi_mdrD,lo_mdrD;
	//execute stage
	wire memwriteE;
	wire [1:0] memsizeE;
	wire memsigndE;
	//memory stage

	//writeback stage

	maindec md(
		opD,functD,rtD,
		mfhiD,mfloD,
		hi_writeD,lo_writeD,
		hi_mdrD,lo_mdrD,
		memtoregD,memwriteD,
		branchD,alusrcD,
		regdstD,regwriteD,
		jumpD,jalD,jrD,balD,
		memsizeD,
		memsigndD
		);
	aludec ad(functD,opD,alucontrolD);

	assign pcsrcD = branchD & equalD;

	wire regwriteD2E;
	assign regwriteD2E=regwriteD||(balD & equalD)||jalD;

	//pipeline registers
	flopenrc #(20) regE(
		clk,
		rst,
		~stallE,
		flushE,
		{memtoregD,memwriteD,alusrcD,regdstD,regwriteD2E,alucontrolD,jalD,balD,memsizeD,memsigndD,hi_mdrD,lo_mdrD},
		{memtoregE,memwriteE,alusrcE,regdstE,regwriteE,alucontrolE,jalE,balE,memsizeE,memsigndE,hi_mdrE,lo_mdrE}
		);
	flopr #(6) regM(
		clk,rst,
		{memtoregE,memwriteE,regwriteE,memsizeE,memsigndE},
		{memtoregM,memwriteM,regwriteM,memsizeM,memsigndM}
		);

	flopr #(5) regW(
		clk,rst,
		{memtoregM,regwriteM,memsizeM,memsigndM},
		{memtoregW,regwriteW,memsizeW,memsigndW}
		);

	flopenrc #(4) DE_signals(
	clk,rst,
	~stallE,
	flushE,
	{mfhiD,mfloD, hi_writeD, lo_writeD},
	{mfhiE,mfloE, hi_writeE, lo_writeE}
	);

	flopr #(2) EM_signals(
		clk,rst,
		{hi_writeE, lo_writeE},
     	{hi_writeM, lo_writeM}
		);

	flopr #(2) MW_signals(
		clk,rst,
		{hi_writeM, lo_writeM},
     	{hi_writeW, lo_writeW}
		);
endmodule
